import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import Lasso # L1正则化
from sklearn.linear_model import Ridge # L2正则化
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error  # 计算均方误差

def overfitting():
    """
    演示模型过拟合
    """
    # 1 准备数据x y(增加上噪声)
    np.random.seed(666)
    x = np.random.uniform(-3, 3, size=100)
    y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
    # 2 实例化线性回归模型
    estimator = LinearRegression()

    # 3 训练模型
    X = x.reshape(-1, 1)
    X2 = np.hstack([X, X ** 10, X ** 15, X ** 20, X ** 25, X ** 30, X ** 40])  # 数据增加多次项
    estimator.fit(X2, y)

    # 4 模型预测
    y_predict = estimator.predict(X2)

    # 5 计算均方误差
    myret = mean_squared_error(y, y_predict)
    print('myret-->', myret)

    # 6 画图
    plt.scatter(x, y)
    # 画图plot折线图时 需要对x进行排序, 取x排序后对应的y值
    plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
    plt.show()

def l1():
    """
    演示模型过拟合_L1处理
    """
    # 1 准备数据x y(增加上噪声)
    np.random.seed(666)
    x = np.random.uniform(-3, 3, size=100)
    y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)

    # 2 实例化线性回归模型
    estimator = Lasso() # 使用L1正则拟合处理

    # 3 训练模型
    X = x.reshape(-1, 1)
    X2 = np.hstack([X, X ** 10, X ** 15, X ** 20, X ** 25, X ** 30, X ** 40])  # 数据增加多次项
    estimator.fit(X2, y)

    # 4 模型预测
    y_predict = estimator.predict(X2)
    # 5 计算均方误差
    myret = mean_squared_error(y, y_predict)
    print('myret-->', myret)

    # 6 画图
    plt.scatter(x, y)
    # 画图plot折线图时 需要对x进行排序, 取x排序后对应的y值
    plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
    plt.show()

def l2():
    """
    演示模型过拟合_L2正则处理
    """
    # 1 准备数据x y(增加上噪声)
    np.random.seed(666)
    x = np.random.uniform(-3, 3, size=100)
    y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
    # 2 实例化线性回归模型
    estimator = Ridge()  # L2正则处理

    # 3 训练模型
    X = x.reshape(-1, 1)
    X2 = np.hstack([X, X ** 10, X ** 15, X ** 20, X ** 25, X ** 30, X ** 40])  # 数据增加多次项
    estimator.fit(X2, y)

    # 4 模型预测
    y_predict = estimator.predict(X2)
    # 5 计算均方误差
    myret = mean_squared_error(y, y_predict)
    print('myret-->', myret)

    # 6 画图
    plt.scatter(x, y)
    # 画图plot折线图时 需要对x进行排序, 取x排序后对应的y值
    plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
    plt.show()


if __name__ == '__main__':
    overfitting()
    l1()     # 使用L1正则化，减缓过拟合
    l2()     # 使用L2正则化，减缓过拟合
